#include <stdlib.h>
#include <string.h>
#include "util.h"
#include "defs.h"

/**
 * Opens the log file for reading, creating a struct containing the path and the pointer
 * @param log_file_path the constant path to the log file
 * @return The log_file struct containing the opened log file
 */
log_file * open_log_file(const char * log_file_path) {
	// get a log_file struct and put it into memory
	log_file * lf        = (log_file *) malloc(sizeof(log_file));
	lf->log_file_path    = log_file_path;
	// open the log file for reading
	lf->log_file_pointer = fopen(lf->log_file_path, "r");
	return lf;
}

/**
 * Retrieves a line from the file an initializes a struct containing the line's contents and the number of chars in the line
 *
 * This function allocates memory for the log_line constant, which will need to be freed via the free_log_line function
 *
 * @param lf the readable log_file struct constant
 * @return The pointer to the log line
 */
log_line * get_line_from_file(const log_file * lf) {
	// return a null pointer if we have reached the end of the file
	if(feof(lf->log_file_pointer)) {
		log_line * ll = 0;
		return ll;
	}

	// max line length plus 1 for the null terminator
	int mlength    = LINE_LENGTH_MAX + 1;

	// allocate memory for the log_line struct and its dynamic members
	log_line * ll  = (log_line *) malloc(sizeof(log_line));
	ll->line_contents = (char *) malloc(sizeof(char) * mlength);

	char * st = fgets(ll->line_contents, mlength, lf->log_file_pointer);
	if(!st) {
		free(ll); // free the memory and just return a null pointer
		ll = 0;
	} else {
		ll->line_length = strlen(ll->line_contents);
	}

	return ll;
}

/**
 * Prints the current log line out to the provided file pointer
 *
 * @param ll the current log file line
 * @param out the file pointer in which to send the output
 * @param st the current application settings
 */
void print_log_line(const log_line * ll, FILE * out, const settings * st) {
	fprintf(out,"%s\n", ll->line_contents);
}

/**
 * Releases the memory allocated for a log_line pointer
 *
 * @param line the log_line pointer to the memory to be freed
 */
void free_log_line(log_line * line) {
	free(line->line_contents);
	free(line);
}

/**
 * Closes the log file and frees the memory allocated for its struct
 *
 * @param lf the current log file
 */
void free_log_file(log_file * lf) {
	// close the pointer to the log file
	fclose(lf->log_file_pointer);
	// free the memory allocated for the struct
	free(lf);
}

parsed_log_entry * create_parsed_log_entry() {
	parsed_log_entry * ple = (parsed_log_entry *)malloc(sizeof(parsed_log_entry));
	return ple;
}

void free_parsed_log_entry(parsed_log_entry * ple) {
	free(ple->remote_host);
	free(ple->local_host);
	free(ple->client_identity);
	free(ple->remote_user);
	free(ple->time);
	free(ple->request_string);
	free(ple->request_uri);
	free(ple->user_agent);
	free(ple);
	ple = 0;
}

